package com.tedu.API.IO;

import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 标准IO流----目的：数据传输 输出文本，输出图片
 * java定义一套标准流--->数据传输---->创建某个流的对象
 * 标准流规则1> : 方向划分  ---- 输出流和输入流
 *                输入流    读入---文件 相对于程序----文件往程序里面走
 *                InputStream(抽象类:定义了所有读的写法)
 *                输出流    写 ---文件--->相对于--->程序写出
 *                OutputStream(抽象类：定义所有写的方法)
 *         2> 功能划分
 *         低级流【节点流】:是建立在程序和数据源的“管道”
 *                  功能：负责搬运的数据流，输入流和输出流都有自己的低级流
 *                  特点：一个字节的一个字节读或者写的方法
 *           FileOutputStream  低级流继承InputStream --- 文件输出流
 *           FileInputStream   低级流继承OutputStream ---文件输入流
 *         高级流【处理流】：不能独立存在，不能直接创建对象
 *                 功能：专门处理低级流以及其他高级流的流
 *                 特点：搬运数据时实现具体的功能：效率提高的流
 *
 *  ----总结：输入流和输出流，具备功能：低级流和高级流，实际使用：明确使用具体的流
 */
public class IOAPI {
    /**
     * 标准流    方向：输入流         低级流
     *              输出流         高级流
     *
     *     文件输出流  FileOutputStream
     * 需求：写出一个文件 fos.txt
     * FileOutputStream 构造器的使用
     * new FileOutputStream("路径+全称")
     * new FileOutputStream("路径+全称",boolean append)
     * 写文件的同时实现追加的效果，第二个参数：true  追加
     *                                 false 不追加
     *new FileOutputStream(File file,boolean append)
     * 写出文件，采用File文件，路径+全称
     */
    @Test
    public void testFOS() throws IOException {
        //低级流 ----文件的输出流对象
        FileOutputStream fos=new FileOutputStream("fos.txt",true);
        //需求：fos.txt增加一行文本,每一次运行实现追加的效果
        String say="独one无two";   //字符串由字符数组构成---数组的功能 getBytes()转换为字节数组
        //输出流具备写的功能 ： write(byte[] b) 写出字节数组
        fos.write(say.getBytes());//里面可以传编码集
        //关闭流---目的：节约内存的开销
        fos.close();
    }

    /**
     * 文件的输入流：读入操作
     * FileInputStream 文件的输入流
     * read() 返回一个读取的字节---效率低
     * read(字节数组byte[] b)返回一个指定字节数组的空间---效率高
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS() throws IOException {
        //创建文件输入流--读入数据：fos.txt
        FileInputStream fis=new FileInputStream("fos.txt");
        //读入效率高：创建字节数组-指定空间为：10kb
        byte[] data=new byte[1024*10];
        //读入操作：read(字节数组)
        int len=fis.read(data);
        //写出：文本--字符串--针对流操作，提供构造器
        //                 将文件按照指定字节数组空间“写入程序当中”
        //                  len：将十进制转换为二进制，写入
        //                  从0开始写入程序，写到-1结束
        //一次性将给定数据按照字节数组指定空间大小，写出字符串
        String str=new String(data,0,len);
        System.out.println("打印Fos。txt文件"+str);
    }

    /**
     * 需求：利用标准流实现视频的复制和粘贴
     */
    @Test
    public void testCV() throws IOException {
        //创建读入流
        FileInputStream fis=new FileInputStream("复制使用.mp4");
//        byte[] data=new byte[1024*100];

        //2.粘贴写出
        FileOutputStream fos=new FileOutputStream("afterVideo.mp4");
        //3.保存每次读取的数据【字节量--int】
        int middle=-1;
        //4.1一直 从复制视频进行读入操作
        //时间
        long startTime=System.currentTimeMillis();
        while((middle= fis.read())!=-1){
            //4.2同时写出新文件
            fos.write(middle);
        }
        long endTime=System.currentTimeMillis();
        //5关闭流
        fis.close();
        fos.close();
        System.out.println("所需要时间"+(endTime-startTime));
    }

    /**
     * 需求：利用标准流实现视频复制粘贴---效率低
     *                            效率高--->空间执行能力：自定：100kb
     *   【高级流】BufferedInputStream   缓冲输入流---提升效率：字节数组【长度不确定，按照文件大小进行分配】
     *           BufferedOutputStream  缓冲输出流----提升效率：字节数组【长度不确定，按照文件大小进行分配】
     *   高级流使用方式：1.处理低级流，套在低级流上
     *                写法：new 高级流(传入低级流的引用)
     *                2.直接使用高级流的方法
     *                3.高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
        //创建低级流：读入 “复制视频”
        FileInputStream fis=
                new FileInputStream("复制使用.mp4");
        //创建高级流：套在低级流上
        BufferedInputStream bis=
                new BufferedInputStream(fis);

        //创建低级流 写出文件“efficiency.mp4”
        FileOutputStream fos=
                new FileOutputStream("efficiency.mp4");
        //创建高级流
        BufferedOutputStream bos=
                new BufferedOutputStream(fos);

        //保存数据
        int len = -1;
        //4.高级流---低级流一样
        //一直从“复制视频.mp4”读取数据，不等于-1一直读取
        //高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
        //高级流--低级流方法一致---write() 写出内嵌缓冲区【字节数组】
        long start = System.currentTimeMillis();
        while ((len = bis.read()) != -1) {
            bos.write(len);
        }
        long end = System.currentTimeMillis();
        System.out.println(" " + (end - start));
        //关闭流---高级流于低级流：都关--->高级流间接关闭低级流
        bis.close();  //高级缓冲输入流
        bos.close();  //高级缓冲输出流
        fis.close();  //低级流
        fos.close();
    }

    /**
     * 高级流---缓冲流【内嵌缓冲区】
     * BufferedOutputStream  缓冲输出流
     *
     * 需求：通过缓冲输出流实现从程序写出文件：bos.txt ，写出内容
     */
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流--->bos.txt
        FileOutputStream fos=
                new FileOutputStream("bos.txt");
        //2.创建高级流--->具备缓冲区：字节数组
        BufferedOutputStream bos=
                new BufferedOutputStream(fos);
        //3.写出文件的文本内容
        String str="50块的张梦涛30块的王克外加白给的小烧淼";
        //4.写出的文本内容写出到bos.txt中：字符串转换成字节数组--写出
        bos.write(str.getBytes());
        //5.将缓冲区的数据一次性进行写出flush() 【立即写出】
//        bos.flush();
        bos.close();  //关闭流---一定把缓冲区数据全部
    }

    /**
     * 标准的IO-->成对【低级流+高级】结合异常--数据传输成功【异常捕获】
     * 重构 testBOS()单元测试
     */
    @Test
    public void testBOSIO(){
        //1.置空流---提升所有流的作用域：增加使用范围
        FileOutputStream fos=null;   //低级流：搬运数据
        BufferedOutputStream bos=null; //高级流：缓冲输出流
        //2.捕获流异常并且做出处理
        try {
            fos=new FileOutputStream("bos.txt");
            bos=new BufferedOutputStream(fos);
            bos.write("张大涛：四个大字啊~~~邯郸夹子儿".getBytes());
            bos.flush();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {//IO流”中”异常：小异常父类
            e.printStackTrace();
        }catch (Exception e){//最大的异常 Exception
            e.printStackTrace();
        }
        finally {//一定会执行的代码块
            //3.关闭流---高级流---释放资源
            //判断：高级流不为null,关闭
            if (bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

    /**
     * 改版
     */
    @Test
    public void testFOSIO(){
        //写出一个文件fos.txt
        //创建低级流
        FileOutputStream fos=null;
        String say="涛子";
        try {
            fos=new FileOutputStream("fos.txt",true);
            fos.write(say.getBytes());
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        finally {
            //关闭流
            if (fos!=null)
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

    @Test
    public void testFISIO(){
        //需求:数组自定义，读入fos.txt
        FileInputStream fis=null;
        byte[] b=new byte[1024*10];
        try {
            fis=new FileInputStream("fos.txt");
            int i=fis.read(b);
            String str=new String(b,0,i);
            System.out.println(str);
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        finally {
            //关闭流
            if (fis!=null)
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

    }

    @Test
    public void testCVIO(){
        //需求：复制粘贴“复制使用”
        //创建置空流，并且读入流和写入低级流，一个字节一个字节
        FileInputStream fis=null;
        FileOutputStream fos=null;

        //创建中间量
        int middle=-1;

        //一直读入和写出
        try {
            fis=new FileInputStream("复制使用.mp4");
            fos=new FileOutputStream("afterVideo.mp4");
            while((middle=fis.read())!=-1){
                fos.write(middle);
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        finally {
            //关闭流
            try {
                if (fis!=null)
                    fis.close();
                if (fos!=null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testCVSIO(){
        //需求：高效率的粘贴复制，使用Buffered高级流
        //创建置空流，低级流和高级流
        FileInputStream fis=null;
        FileOutputStream fos=null;

        BufferedInputStream bis=null;
        BufferedOutputStream bos=null;
        //中间量
        int middle=-1;
        //new 低级流和高级流
        try {
            fis=new FileInputStream("复制使用.mp4");
            bis=new BufferedInputStream(fis);
            fos=new FileOutputStream("afterVideo.mp4");
            bos=new BufferedOutputStream(fos);
            //一直
            while((middle=bis.read())!=-1){
                bos.write(middle);
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e) {
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        finally {
            //关闭流
            try {
                if (bis!=null)if (bos!=null)
                    bis.close();
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
